package org.g4studio.core.orm.xibatis.sqlmap.client;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * This interface declares methods for demarcating SQL Map transactions.
 * 
 * @see SqlMapSession
 * @see SqlMapClient
 */
public interface SqlMapTransactionManager {

	/**
	 * Demarcates the beginning of a transaction scope. Transactions must be
	 * properly committed or rolled back to be effective. Use the following
	 * pattern when working with transactions:
	 * 
	 * <pre>
	 * try {
	 * 	sqlMap.startTransaction();
	 * 	// do work
	 * 	sqlMap.commitTransaction();
	 * } finally {
	 * 	sqlMap.endTransaction();
	 * }
	 * </pre>
	 * <p/>
	 * Always call endTransaction() once startTransaction() has been called.
	 * 
	 * @throws java.sql.SQLException
	 *             If an error occurs while starting the transaction, or the
	 *             transaction could not be started.
	 */
	public void startTransaction() throws SQLException;

	/**
	 * Demarcates the beginning of a transaction scope using the specified
	 * transaction isolation. Transactions must be properly committed or rolled
	 * back to be effective. Use the following pattern when working with
	 * transactions:
	 * 
	 * <pre>
	 * try {
	 * 	sqlMap.startTransaction(Connection.TRANSACTION_REPEATABLE_READ);
	 * 	// do work
	 * 	sqlMap.commitTransaction();
	 * } finally {
	 * 	sqlMap.endTransaction();
	 * }
	 * </pre>
	 * <p/>
	 * Always call endTransaction() once startTransaction() has been called.
	 * 
	 * @throws java.sql.SQLException
	 *             If an error occurs while starting the transaction, or the
	 *             transaction could not be started.
	 */
	public void startTransaction(int transactionIsolation) throws SQLException;

	/**
	 * Commits the currently started transaction.
	 * 
	 * @throws SQLException
	 *             If an error occurs while committing the transaction, or the
	 *             transaction could not be committed.
	 */
	public void commitTransaction() throws SQLException;

	/**
	 * Ends a transaction and rolls back if necessary. If the transaction has
	 * been started, but not committed, it will be rolled back upon calling
	 * endTransaction().
	 * 
	 * @throws SQLException
	 *             If an error occurs during rollback or the transaction could
	 *             not be ended.
	 */
	public void endTransaction() throws SQLException;

	/**
	 * Allows the developer to easily use an externally supplied connection when
	 * executing statements.
	 * <p/>
	 * <b>Important:</b> Using a user supplied connection basically sidesteps
	 * the transaction manager, so you are responsible for appropriately. Here's
	 * a (very) simple example (throws SQLException):
	 * 
	 * <pre>
	 * try {
	 * 	Connection connection = dataSource.getConnection();
	 * 	sqlMap.setUserConnection(connection);
	 * 	// do work
	 * 	connection.commit();
	 * } catch (SQLException e) {
	 * 	try {
	 * 		if (connection != null)
	 * 			commit.rollback();
	 * 	} catch (SQLException ignored) {
	 * 		// generally ignored
	 * 	}
	 * 	throw e; // rethrow the exception
	 * } finally {
	 * 	try {
	 * 		if (connection != null)
	 * 			connection.close();
	 * 	} catch (SQLException ignored) {
	 * 		// generally ignored
	 * 	}
	 * }
	 * </pre>
	 * 
	 * @param connnection
	 * @throws SQLException
	 */
	public void setUserConnection(Connection connnection) throws SQLException;

	/**
	 * Returns the current user supplied connection as set by
	 * setUserConnection().
	 * <p/>
	 * TODO : DEPRECATED
	 * 
	 * @return The current user supplied connection.
	 * @throws SQLException
	 * @deprecated Use getCurrentConnection() instead.
	 */
	public Connection getUserConnection() throws SQLException;

	/**
	 * Returns the current connection in use. If no connection exists null will
	 * be returned. There may be no connection if no transaction has been
	 * started, and if no user provided connection has been set.
	 * 
	 * @return The current connection or null.
	 * @throws SQLException
	 */
	public Connection getCurrentConnection() throws SQLException;

	/**
	 * Returns the DataSource instance currently being used by the
	 * SqlMapSession.
	 * 
	 * @return The DataSource instance currently being used by the
	 *         SqlMapSession.
	 */
	public DataSource getDataSource();

}
